package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.common.exception.CustomException;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.PageResponseVO;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.mess.NewsUpOrDownMess;
import com.heima.model.wemedia.dtos.WmNewsDownOrUpDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.vo.ContentVO;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.entity.MaterialIdAndType;
import com.heima.wemedia.mapper.ChannelMapper;
import com.heima.wemedia.mapper.MaterialMapper;
import com.heima.wemedia.mapper.MaterialNewsMapper;
import com.heima.wemedia.mapper.NewsMapper;
import com.heima.wemedia.service.AutoScanService;
import com.heima.wemedia.service.ChannelService;
import com.heima.wemedia.service.NewsService;
import com.sun.org.apache.bcel.internal.generic.NEW;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author brianxia
 * @version 1.0
 * @date 2022-11-13 9:51
 */
@Service
@Slf4j
public class NewsServiceImpl extends ServiceImpl<NewsMapper, WmNews> implements NewsService {

    @Autowired
    private MaterialNewsMapper materialNewsMapper;
    @Autowired
    private MaterialMapper materialMapper;
    @Autowired
    private AutoScanService autoScanService;
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    @Override
    public PageResponseResult findNews(WmNewsPageReqDto dto) {

        LambdaQueryWrapper<WmNews> wrapper = Wrappers.<WmNews>lambdaQuery()
                .eq(WmNews::getUserId, WmThreadLocalUtil.getUser().getId())
                .orderByDesc(WmNews::getPublishTime);

        //对条件进行判断

        //1.文章状态
        if(dto.getStatus() != null){
            wrapper.eq(WmNews::getStatus,dto.getStatus());
        }
        //2.关键字
        if(StringUtils.isNotBlank(dto.getKeyword())){
            wrapper.like(WmNews::getTitle,dto.getKeyword());
        }
        //3.频道列表
        if(dto.getChannelId() != null){
            wrapper.eq(WmNews::getChannelId,dto.getChannelId());
        }
        //4.发布时间
        if(dto.getBeginPubDate() != null && dto.getEndPubDate() != null){
            wrapper.between(WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate());
        }

        Page<WmNews> page = page(new Page<>(dto.getPage(), dto.getSize()),
                wrapper);

        PageResponseResult pageResponseResult = new PageResponseResult((int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal());
        pageResponseResult.setData(page.getRecords());
        return pageResponseResult;
    }

    @Override
    public PageResponseVO findNews2(WmNewsPageReqDto dto) {
        LambdaQueryWrapper<WmNews> wrapper = Wrappers.<WmNews>lambdaQuery()
                .eq(WmNews::getUserId, WmThreadLocalUtil.getUser().getId())
                .orderByDesc(WmNews::getPublishTime);

        //对条件进行判断

        //1.文章状态
        if(dto.getStatus() != null){
            wrapper.eq(WmNews::getStatus,dto.getStatus());
        }
        //2.关键字
        if(StringUtils.isNotBlank(dto.getKeyword())){
            wrapper.like(WmNews::getTitle,dto.getKeyword());
        }
        //3.频道列表
        if(dto.getChannelId() != null){
            wrapper.eq(WmNews::getChannelId,dto.getChannelId());
        }
        //4.发布时间
        if(dto.getBeginPubDate() != null && dto.getEndPubDate() != null){
            wrapper.between(WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate());
        }

        Page<WmNews> page = page(new Page<>(dto.getPage(), dto.getSize()),
                wrapper);

        PageResponseVO vo = new PageResponseVO(page.getTotal(),
                    page.getSize(),page.getCurrent(),page.getRecords());

        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(WmNewsDto dto) {
        WmNews wmNews = new WmNews(); //数据库实体
        //属性名和类型必须一致
        BeanUtils.copyProperties(dto,wmNews); //封面图片images类型不一致，无法拷贝

        //处理自动选择封面
        String content = dto.getContent(); //“[{},{type:image,value:url}]”
        List<ContentVO> contentVOS = JSONArray.parseArray(content, ContentVO.class);

        //处理文章封面图片
        List<String> contentUrls =  dealArticleImages(dto, wmNews, contentVOS);

        //保存数据库
        wmNews.setUserId(WmThreadLocalUtil.getUser().getId());
        if(dto.getStatus().equals(WmNews.Status.SUBMIT.getCode())){
            wmNews.setSubmitedTime(new Date());
        }

        if(dto.getId() == null){
            //新增
            wmNews.setCreatedTime(new Date());
            wmNews.setEnable((short)1);

            save(wmNews);
        }else{
            //更新
            updateById(wmNews);
            //把文章和所有图片关联关系 删除
            materialNewsMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery()
                    .eq(WmNewsMaterial::getNewsId,dto.getId())
            );
        }

        //重建 图片和文章关联关系
        //封面
        List<MaterialIdAndType> materialIdAndTypes = new ArrayList<>();

        dealImageAndNewsRelation(dto.getImages(),
                WemediaConstants.WM_COVER_REFERENCE,materialIdAndTypes);


        //内容
        dealImageAndNewsRelation(contentUrls,WemediaConstants.WM_CONTENT_REFERENCE,materialIdAndTypes);

        if(CollectionUtils.isNotEmpty(materialIdAndTypes)){
            //有图片，存到数据库中
            materialNewsMapper.insertBatch2(materialIdAndTypes,wmNews.getId());
        }

        System.out.println(Thread.currentThread().getName());
        //发布之后判断如果要审核

        //发消息给mq,封装wmnews对象 服务中编写消费者，消费对象执行审核逻辑

        if(dto.getStatus().equals(WmNews.Status.SUBMIT.getCode())){
            autoScanService.autoScan(wmNews);
        }

    }

    @Override
    public void downOrUp(WmNewsDownOrUpDto dto) {

        //1.根据id查询文章
        WmNews wmNews = getById(dto.getId());
        if(wmNews == null){
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //判断文章是否发布
        if(!Objects.equals(wmNews.getStatus(), WmNews.Status.PUBLISHED.getCode())){
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        //修改数据库中enable字段
//        wmNews.setEnable(dto.getEnable());
//        updateById(wmNews);
        boolean update = update(Wrappers.<WmNews>lambdaUpdate()
                .eq(WmNews::getId, dto.getId())
                .set(WmNews::getEnable, dto.getEnable())
                .eq(WmNews::getUserId, WmThreadLocalUtil.getUser().getId())
        );
        if(!update){
            throw new CustomException(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }

        //发送消息
        NewsUpOrDownMess mess = new NewsUpOrDownMess();
        mess.setArticleId(wmNews.getArticleId());
        mess.setEnable(dto.getEnable());
        kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC,
                JSON.toJSONString(mess));

    }

    private void dealImageAndNewsRelation(List<String> urls,short type,List<MaterialIdAndType> results){


        if(CollectionUtils.isEmpty(urls)){
            return;
        }

        //1.将url转换成id
        //select 所有字段 -> select id
        List<WmMaterial> wmMaterials = materialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery()
                .in(WmMaterial::getUrl, urls).select(WmMaterial::getId)
        );
        //所有素材id
        List<Integer> ids = wmMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());

//        //素材ids 文章id 类型type 批量写入数据库
//        materialNewsMapper.insertBatch(ids,wmNews.getId(),type);


        if(ids != null){
            for (Integer coverId : ids) {
                MaterialIdAndType materialIdAndType = new MaterialIdAndType();
                materialIdAndType.setType(type);
                materialIdAndType.setId(coverId);

                results.add(materialIdAndType);
            }
        }
    }

    private List<String> dealArticleImages(WmNewsDto dto, WmNews wmNews, List<ContentVO> contentVOS) {
        //for循环
//        Set<String> urls = new HashSet<>();
//        for (ContentVO contentVO : contentVOS) {
//            if(WemediaConstants.WM_NEWS_TYPE_IMAGE.equals(contentVO.getType())){
//                //图片
//                String url = contentVO.getValue();
//                urls.add(url);
//            }
//        }
//
//        List<String> urlList = new ArrayList<>(urls);

        // stream流 方式来改造代码 1.创建流 2.流运算(筛选 取值 去重) 3.输出集合 collect
        List<String> urls = contentVOS.stream()
                .filter(contentVO -> WemediaConstants.WM_NEWS_TYPE_IMAGE.equals(contentVO.getType()))
                .map(ContentVO::getValue)
                .distinct()
                .collect(Collectors.toList());

        //判断如果是自动，获取内容中的图片作为封面
        if(Objects.equals(WemediaConstants.WM_NEWS_TYPE_AUTO, dto.getType())){

            int size = urls.size();
            if(size >= 3){
                //>=3张 取前三张 3图
                dto.setImages(urls.subList(0,3));
                wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
            }else if (size > 0){
                //1-2张 单图，取第一张
                dto.setImages(urls.subList(0,1));
                wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
            }else{
                //0张 无图
                dto.setImages(null);
                wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            }

        }

        //处理数据库中的images
        if(CollectionUtils.isNotEmpty(dto.getImages())){
            //用逗号分隔字符串，写入数据库实体类中
            String join = StringUtils.join(dto.getImages(), ",");
            //String[] split = join.split(",");
            wmNews.setImages(join);
        }

        return urls;
    }
}
